package com.tom.demo.service.system.impl;

import cn.hutool.core.lang.Snowflake;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tom.demo.common.entity.SysMenu;
import com.tom.demo.common.entity.SysRole;
import com.tom.demo.common.entity.SysRoleMenu;
import com.tom.demo.common.enumeration.ResponseEnum;
import com.tom.demo.common.exception.CustomException;
import com.tom.demo.common.response.Result;
import com.tom.demo.common.utils.RecursiveMenuUtil;
import com.tom.demo.common.utils.SecurityUtils;
import com.tom.demo.dto.AssignRoleMenuDto;
import com.tom.demo.dto.RoleEditDto;
import com.tom.demo.dto.RoleSearchDto;
import com.tom.demo.mapper.SysMenuMapper;
import com.tom.demo.mapper.SysRoleMapper;
import com.tom.demo.mapper.SysRoleMenuMapper;
import com.tom.demo.mapper.SysUserRoleMapper;
import com.tom.demo.service.system.RoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class RoleServiceImpl implements RoleService {

    @Resource
    private SysRoleMapper sysRoleMapper;

    @Resource
    private SysUserRoleMapper sysUserRoleMapper;

    @Resource
    private Snowflake snowflake;

    @Resource
    private SysMenuMapper sysMenuMapper;

    @Resource
    private SysRoleMenuMapper sysRoleMenuMapper;

    @Override
    public Result pageList(Integer page, Integer pageSize, RoleSearchDto roleSearchDto) {
        PageHelper.startPage(page,pageSize);
        List<SysRole> roleList =  sysRoleMapper.pageList(roleSearchDto);
        PageInfo<SysRole> pageInfo = new PageInfo<>(roleList);
        return Result.success(pageInfo);
    }

    @Override
    public Result updateRoleStatus(String roleId, Boolean status) {
        SysRole sysRole = sysRoleMapper.selectByPrimaryKey(roleId);
        sysRole.setStatus(status);
        sysRole.setUpdateBy(SecurityUtils.getLoginUserName());
        sysRole.setUpdateTime(new Date());
        int row = sysRoleMapper.updateByPrimaryKey(sysRole);
        return row > 0 ? Result.success():Result.error("修改角色状态失败");
    }

    @Override
    public Result findByRoleId(String roleId) {
        SysRole sysRole = sysRoleMapper.selectByPrimaryKey(roleId);
        return Result.success(sysRole);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result deleteByRoleId(String roleId) {
        //先去删除关联表
        sysUserRoleMapper.deleteByRoleId(roleId);
        //再删除角色
        sysRoleMapper.deleteByPrimaryKey(roleId);
        return Result.success();
    }

    @Override
    public Result insertRole(RoleEditDto roleEditDto) {
        String roleName = roleEditDto.getRoleName();
        int roleNameOne =  sysRoleMapper.findOne(roleName,null,null);
        if(roleNameOne > 0){
            throw new CustomException(ResponseEnum.ROLE_NAME_DATA_EXIST);
        }
        String roleKey = roleEditDto.getRoleKey();
        int roleKeyOne = sysRoleMapper.findOne(null, roleKey,null);
        if(roleKeyOne > 0){
            throw new CustomException(ResponseEnum.ROLE_KEY_DATA_EXIST);
        }
        SysRole sysRole = new SysRole();
        BeanUtils.copyProperties(roleEditDto,sysRole);
        sysRole.setRoleId(snowflake.nextIdStr());
        sysRole.setCreateBy(SecurityUtils.getLoginUserName());
        sysRole.setCreateTime(new Date());
        int row = sysRoleMapper.insert(sysRole);
        return row > 0 ? Result.success():Result.error("添加角色失败");
    }

    @Override
    public Result updateRole(RoleEditDto roleEditDto) {
        String roleId = roleEditDto.getRoleId();
        if(!StringUtils.hasText(roleId)){
            return Result.error("角色id不能为空");
        }
        String roleName = roleEditDto.getRoleName();
        int roleNameOne =  sysRoleMapper.findOne(roleName,null,roleId);
        if(roleNameOne > 0){
            throw new CustomException(ResponseEnum.ROLE_NAME_DATA_EXIST);
        }
        String roleKey = roleEditDto.getRoleKey();
        int roleKeyOne = sysRoleMapper.findOne(null, roleKey,roleId);
        if(roleKeyOne > 0){
            throw new CustomException(ResponseEnum.ROLE_KEY_DATA_EXIST);
        }
        SysRole sysRole = sysRoleMapper.selectByPrimaryKey(roleId);
        sysRole.setRoleName(roleName);
        sysRole.setRoleKey(roleKey);
        sysRole.setRoleSort(roleEditDto.getRoleSort());
        sysRole.setUpdateTime(new Date());
        sysRole.setUpdateBy(SecurityUtils.getLoginUserName());
        sysRole.setRemark(roleEditDto.getRemark());
        int row = sysRoleMapper.updateByPrimaryKey(sysRole);
        return row > 0 ? Result.success():Result.error("修改角色信息失败");
    }

    @Override
    public Result toAssign(String roleId) {
        //1:先查询所有的菜单
        List<SysMenu> sysMenusAll = sysMenuMapper.findMenuAll();

        //2:查询当前角色已经拥有的菜单
        List<SysMenu> sysMenus =  sysMenuMapper.findByRoleMenus(roleId);
        //收集已经选中的菜单id
        List<String> menuIds = sysMenus.stream().map(SysMenu::getMenuId).collect(Collectors.toList());
        if(!CollectionUtils.isEmpty(sysMenusAll)){
            //如果当前角色id数组中包含，则将这条数据的选中状态置为true
            sysMenusAll.forEach(item-> item.setSelected(menuIds.contains(item.getMenuId())));
        }
        //构建为树形结构菜单返回
        List<SysMenu> buildMenuTree = RecursiveMenuUtil.buildMenuTree(sysMenusAll);
        return Result.success(buildMenuTree);
    }

    @Override
    public Result doAssign(AssignRoleMenuDto assignRoleMenuDto) {
        String roleId = assignRoleMenuDto.getRoleId();
        //1:先去删除角色之前已经分配关联关系删除掉
        sysRoleMenuMapper.deleteByRoleId(roleId);
        //2:再去重新添加角色和菜单的关联关系
        List<String> menuIds = assignRoleMenuDto.getMenuIds();
        if(!CollectionUtils.isEmpty(menuIds)){
            menuIds.forEach(menuId->{
                SysRoleMenu sysRoleMenu = new SysRoleMenu();
                sysRoleMenu.setRoleId(roleId);
                sysRoleMenu.setMenuId(menuId);
                sysRoleMenuMapper.insert(sysRoleMenu);
            });
        }
        return Result.success();
    }
}
